package com.ouroboroswiki.core.content.xml;

import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.output.ByteArrayOutputStream;

import com.ouroboroswiki.core.AbstractProxiedContent;
import com.ouroboroswiki.core.Content;
import com.ouroboroswiki.core.ContentException;
import com.ouroboroswiki.core.filter.Filter;

public class XMLTaggingContentProxy extends AbstractProxiedContent {

	@SuppressWarnings("unused")
	private static final Logger log = Logger.getLogger(XMLTaggingContentProxy.class.getName());
	
	private static final String ESCAPED_ELEMENT = "escaped";
	private static final String ORIGINAL_ELEMENT = "original";
	
	private static final Pattern PATTERN = Pattern.compile("<\\w");
	
	private String elementName;
	private String mimeType;
	private boolean escape;
	
	private Filter<String> mimeFilter;

	public XMLTaggingContentProxy( Content proxied, String elementName, boolean escape ) {
		super( proxied );
		this.elementName = elementName;
		this.escape = escape;
	}
	
	public Filter<String> getMimeFilter() {
		return this.mimeFilter;
	}
	
	public void setMimeFilter( Filter<String> mimeFilter ) {
		this.mimeFilter = mimeFilter;
	}
	
	@Override
	public String getMimeType() {
		if( this.mimeType != null ) {
			return this.mimeType;
		} else {
			return super.getMimeType();
		}
	}
	
	public void setMimeType( String mimeType ) {
		this.mimeType = mimeType;
	}

	@Override
	public void write(OutputStream outs) throws IOException, ContentException {
		// TODO do this more efficiently
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		
		outs.write((
				"<?xml version=\"1.0\"?>"+
				"<!DOCTYPE secret_spaces [ <!ENTITY nbsp \"&#160;\"> ]>"+
				"<"+elementName+" name=\""+getUniqueName()+"\" repo=\""+getRepositoryName()+"\">").getBytes()
		);
		if( proxied.exists() && (mimeFilter == null || mimeFilter.accept(proxied.getMimeType()) )) {
			proxied.write(bos);
			byte[] data = bos.toByteArray();
			if( escape ) {
				outs.write(("<"+ESCAPED_ELEMENT+"><![CDATA[").getBytes());
				outs.write( data );
				outs.write( ("]]></"+ESCAPED_ELEMENT+">").getBytes());
			}
			outs.write(("<"+ORIGINAL_ELEMENT+">").getBytes());
			String s = new String( data );
			// remove any non-xml metadata characters
			Matcher matcher = PATTERN.matcher(s);
			if( matcher.find() ) {
				int start = matcher.start();
				if( start != 0 ) {
					s = s.substring(start);
				}
				outs.write( s.getBytes() );
			}
			outs.write( ("</"+ORIGINAL_ELEMENT+">").getBytes());
		}
		outs.write( ("</"+elementName+">").getBytes());
	}
}
